#include <pthread.h>
#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>

int m, k, **a, *pi; 

void libera_matriz (int m, int n, int **v){
    int i;
    for (i=0; i<m; i++) free (v[i]);
    free (v);
}

int **aloca_matriz(int m, int n) {
	int **v; 
	int i;    
	if (m < 1 || n < 1) { 
		printf("Erro: Parametro invalido");
		return NULL;
	}

	v = (int **) malloc (m * sizeof(int *));
	if (v == NULL) {
		printf("Erro: Memoria Insuficiente");
		return NULL;
	}

	for (i = 0; i < m; i++) {
		v[i] = (int*) malloc (n * sizeof(int));
		if (v[i] == NULL) {
			printf("Erro: Memoria Insuficiente");
			return NULL;
		}
	}
	return v; 
}

int *aloca_vetor(int m) {
	int *v; 

	if (m < 1) { 
		printf("Erro: Parametro invalido");
		return NULL;
	}

	v = (int*) malloc (m * sizeof(int));
	if (v == NULL) {
		printf("Erro: Memoria Insuficiente");
		return NULL;
	}

	return v;
}

void *run(void *num) {

	long long int i = (long long int) num;

	for(int j = 0; j < k; j++) {
		pi[i] += a[i][j] * a[i][j];
	}			

	pthread_exit(NULL);
}

int main(void) {
	while(1) {
		int i, j;

		pthread_t *threads;
		srand(time(NULL));

		printf("\nEntre com as dimensões da matriz: ");
		scanf ("%d %d", &m, &k);
	
		if ((m == 0 && k == 0) || (m != k)) break;

		double ini = time(0); // tempo de inicio
		
		a = aloca_matriz(m, k);
		pi = aloca_vetor(m);

		// inicializa matriz com valores aleatorios (a) e o vetor produto interno (pi) com zero.
		for(i = 0; i < m; i++) {
			for(j = 0; j < k; j++) {
				a[i][j] = rand() % 100; 
			}
			pi[i] = 0;
		}

		threads = (pthread_t*) malloc (m * sizeof(pthread_t));
	
		// cria as threads
    	for (i = 0; i < m; i++) {
        	pthread_create(&threads[i], NULL, run, (void *) i);
    	}

		for(i = 0;i < m; i++)
            pthread_join(threads[i], NULL);		

		printf("\n--------------------\n");
		
		printf("matriz\n");
		
		for(i = 0; i < m; i++) {
			for(j = 0; j < k; j++) {
				printf("%d ", a[i][j]); 
			}
			printf("\n");
		} 

		printf("\n--------------------\n");
		
		
		printf("vetor produto interno\n");
		for(i = 0; i < m; i++) {
			printf("%d ", pi[i]); 
		}

		printf("\n--------------------\n");

		libera_matriz(m, k, a);
		free(pi);

		printf("Tempo de Execucao: %f segundos\n", time(0) - ini);


 	}
	return 0;
}

